<template>
	<view class="container" :style="{width:windowWidth+'px',height:windowHeight+'px'}">
		<cu-custom>
			<block slot="content">录音</block>
		</cu-custom>
		<view class="content ">
			<view class="content_con">
				<view class="image_1">
					<image style="width: 400rpx;height: 400rpx" src="/static/img/recording-white.png"></image>
				</view>
				<view class="num"><text>{{formattedTime }}</text></view>
				<view class="text">录音时长不能低于5S</view>
			</view>
			<view class="list  flex justify-end align-center">
				<view @click="toggleRecording" class="image_2">
					<view class="img">
						<image v-if="!isRecording " style="width: 260rpx;height: 260rpx;" src="/static/img/start.png">
						</image>
						<image v-else style="width: 174rpx;height: 174rpx" src="/static/img/ends.png"></image>
					</view>
					<view class="text_2">{{isRecording ? '结束录制': "点击录制"}}</view>
				</view>
				<view class="image_3 m-t-2" @click="toList(1)">
					<image style="width: 90rpx;height: 80rpx" src="/static/img/recording-file.png"></image>
					<view class="f-16 m-t-4">录音列表</view>
				</view>
				<uni-file-picker v-model="imageValue" file-mediatype="all" @select="fileSelect"  :auto-upload="false"
					limit="1">
					<view class="image_4" >
						<image style="width: 60rpx;height: 80rpx" src="/static/img/recording.png"></image>
						<view class="f-16">上传录音</view>
					</view>
				</uni-file-picker>
				
			</view>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				windowHeight: 650,
				windowWidth: 375,
				isRecording: false,
				mediaRecorder: null, // MediaRecorder实例
				audioChunks: [], // 录音数据块
				startTime: 0, // 录音开始时间
				currentTime: 0, // 当前录音时长(ms)
				timer: null, // 计时器
				audioBlob: null, // 录音Blob对象
				statusMessage: '', // 状态提示信息
				id: 0,
				imageValue: [],
			}
		},
		onLoad(option) {
			this.id = option.id;
			this.windowHeight = uni.getSystemInfoSync().windowHeight;
			this.windowWidth = uni.getSystemInfoSync().windowWidth;
		},
		computed: {
			// 格式化显示的时间 00:00
			formattedTime() {
				const seconds = Math.floor(this.currentTime / 1000)
				const minutes = Math.floor(seconds / 60)
				const remainingSeconds = seconds % 60
				return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`
			}
		},
		methods: {
			// 检查浏览器兼容性
			checkCompatibility() {
				if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
					throw new Error('您的浏览器不支持录音功能')
				}
			},
			// 开始/结束录音
			async toggleRecording() {
				if (this.isRecording) {
					if (this.currentTime < 5000) {
						uni.showToast({
							title: '录音时长不能低于5S',
							icon: 'none'
						})
						return;
					}
					this.stopRecording()
				} else {
					try {
						await this.startRecording()
					} catch (error) {
						console.error('录音失败:', error)
						this.statusMessage = '录音失败: ' + error.message
						uni.showToast({
							title: '录音失败',
							icon: 'none'
						})
					}
				}
			},

			// 开始录音
			async startRecording() {
				this.checkCompatibility()

				try {
					// 1. 获取麦克风权限
					const stream = await navigator.mediaDevices.getUserMedia({
						audio: true
					})

					// 2. 创建MediaRecorder实例
					this.mediaRecorder = new MediaRecorder(stream)
					this.audioChunks = []

					// 3. 设置数据可用时的回调
					this.mediaRecorder.ondataavailable = (event) => {
						if (event.data.size > 0) {
							this.audioChunks.push(event.data)
						}
					}

					// 4. 设置录音停止时的回调
					this.mediaRecorder.onstop = () => {
						// 创建Blob对象
						this.audioBlob = new Blob(this.audioChunks, {
							type: 'audio/mp3'
						})
						console.log('录音完成', this.audioBlob)

						// 停止所有音轨
						stream.getTracks().forEach(track => track.stop())

						// 上传录音
						this.uploadToOSS(this.audioBlob)
					}

					// 5. 开始录音
					this.mediaRecorder.start(1000) // 每1秒收集一次数据
					this.isRecording = true
					this.startTime = Date.now()
					this.startTimer()
					this.statusMessage = '录音中...'

				} catch (error) {
					this.isRecording = false
					throw error
				}
			},

			// 结束录音
			stopRecording() {
				if (this.mediaRecorder && this.isRecording) {
					this.mediaRecorder.stop()
					this.isRecording = false
					this.stopTimer()
					this.statusMessage = '录音完成，准备上传...'
				}
			},

			// 开始计时
			startTimer() {
				this.currentTime = 0
				this.timer = setInterval(() => {
					this.currentTime = Date.now() - this.startTime
					if (this.currentTime > 1000 * 60 * 60 * 2) {
						this.stopRecording()
					}
				}, 1000)
			},

			// 停止计时
			stopTimer() {

				if (this.timer) {
					clearInterval(this.timer)
					this.timer = null
				}
			},

			// 上传到阿里云OSS
			async uploadToOSS(blob) {
				uni.showLoading({
					title: '上传中...'
				})

				try {
					// 1. 首先从你的服务器获取OSS上传凭证
					const tokenResponse = await new Promise((resolve, reject) => {
						// uni.request({
						// 	url: 'https://your-server.com/api/get-oss-token', // 替换为你的后端接口
						// 	method: 'GET',
						// 	success: (res) => resolve(res.data),
						// 	fail: reject
						// })
						let data = {
							filename: '',
							suffix: 'mp3'
						}
						this.$http('/oss/url', data).then(res => {
							let ress = res.data;
							resolve(ress)
						})
					})

					const {
						id,
						host,
						key,
						policy,
						signature,
						url
					} = tokenResponse

					// 2. 生成文件名 (按时间戳)
					const fileName = `audio/${Date.now()}.mp3`

					// 3. 将Blob转换为File对象
					const audioFile = new File([blob], fileName, {
						type: 'audio/mp3'
					})

					// 4. 创建FormData
					const formData = new FormData()
					formData.append('key', key)
					formData.append('policy', policy)
					formData.append('OSSAccessKeyId', id)
					formData.append('signature', signature)
					formData.append('file', audioFile)
					// 5. 使用uni.uploadFile上传到OSS
					const uploadRes = await new Promise((resolve, reject) => {
						uni.showLoading({
							title: '上传中 0%'
						})
						const xhr = new XMLHttpRequest()
						xhr.open('POST', host, true)

						xhr.onload = () => {
							if (xhr.status === 200 || xhr.status === 204) {
								resolve(xhr.responseText)
							} else {
								reject(new Error(`上传失败: ${xhr.status}`))
							}
						}

						xhr.onerror = () => {
							reject(new Error('上传请求失败'))
						}
						xhr.upload.onprogress = (e) => {
							let per = Math.floor((e.loaded / e.total) * 100)

							// 控制进度条最大显示99%，最后请求结束后才变为100%
							if (per > 99) {
								per = 99
							}
							uni.showLoading({
								title: `上传中 ${per}%`
							})
						}
						xhr.send(formData)
					})

					console.log('上传成功', uploadRes)

					this.statusMessage = '上传成功'
					uni.showToast({
						title: '上传成功',
						icon: 'success'
					})

					// 返回的文件URL
					const fileUrl = url;
					let audio_json = {
						src: fileUrl,
						duration: this.currentTime / 1000
					}
					let data = {
						id: this.id,
						audio_json: JSON.stringify(audio_json)
					}
					this.$http('/api/visitsAudio', data).then(res => {
						if (res.code == 200) {
							uni.hideLoading()
							let formData = {
								visit_id: data.id,
							}
							// this.$http('/api/aiAnalysis', formData, 'post').then(ress => {
							// 	if (ress.code == 200) {

							// 	}
							// })
							uni.showToast({
								title: res.message,
								icon: 'none'
							})
							setTimeout(() => {
								this.$store.state.isUpDate = true;
								uni.navigateBack();
							}, 800)
						} else {
							uni.hideLoading()
							uni.showToast({
								title: res.message,
								icon: 'none'
							})
						}
					})
					console.log('文件URL:', fileUrl)

				} catch (error) {
					console.error('上传失败:', error)
					uni.hideLoading()
					this.statusMessage = '上传失败: ' + error.message
					uni.showToast({
						title: '上传失败',
						icon: 'none'
					})
				}
			},
			fileSelect(e) { // 文件选择
				console.log(e)
				let tempFiles= e.tempFiles;
				this.upRec(tempFiles);
			},
			toList(type) {
				if (this.isRecording) {
					uni.showToast({
						title: '录音中...',
						icon: 'none'
					})
					return;
				};
				switch (type) {
					case 1:
						uni.navigateTo({
							url: '/pages/system/recordList?id=' + this.id
						})
						break;
					case 2:
						this.upRec();
						break;
				}
			},
			upRec(tempFiles) {
				// 创建input元素
				// const input = document.createElement('input')
				// input.type = 'file'
				// input.accept = '*/*'

				// input.onchange = (e) => {
				// 	console.log(e);
				// 	const file = e.target.files[0]
				// 	if (!file) return
				// 	console.log(e);
				// 	// 解析音频时长
				// 	this.getAudioDuration(file).then(duration => {
						
				// 		// 上传文件
				// 		this.uploadFile(file,duration)
				// 	})
				// }
				// // 触发文件选择
				// input.click()
				// uni.showLoading({
				// 	title:'获取中'
				// })
				this.imageValue = [];
				console.log(tempFiles);
				let file = tempFiles[0];
				console.log(file);
				
				this.getAudioDuration(file.file).then(duration => {
					// uni.hideLoading();
					// 上传文件
					this.uploadFile(file.file,duration)
				}).catch(rej=>{
					this.uploadFile(file.file,0)
					// uni.hideLoading();
				})
			},
			getAudioDuration(file) {
				return new Promise((resolve) => {
					const audio = new Audio()
					audio.src = URL.createObjectURL(file)

					audio.onloadedmetadata = () => {
						resolve(audio.duration)
						URL.revokeObjectURL(audio.src) // 释放内存
					}

					audio.onerror = () => {
						console.error('获取音频时长失败')
						resolve(0)
					}
				})
			},
			async uploadFile(file,duration) {
				console.log(file)
				uni.showLoading({
					title: '上传中...'
				})
				
				try {
					// 1. 首先从你的服务器获取OSS上传凭证
					const tokenResponse = await new Promise((resolve, reject) => {
						
						let data = {
							filename: '',
							suffix: 'mp3'
						}
						this.$http('/oss/url', data).then(res => {
							let ress = res.data;
							resolve(ress)
						})
					})
				
					const {
						id,
						host,
						key,
						policy,
						signature,
						url
					} = tokenResponse
				
					
				
					// 4. 创建FormData
					const formData = new FormData()
					formData.append('key', key)
					formData.append('policy', policy)
					formData.append('OSSAccessKeyId', id)
					formData.append('signature', signature)
					formData.append('file', file)
					// 5. 使用uni.uploadFile上传到OSS
					const uploadRes = await new Promise((resolve, reject) => {
						uni.showLoading({
							title: '上传中 0%'
						})
						const xhr = new XMLHttpRequest()
						xhr.open('POST', host, true)
				
						xhr.onload = () => {
							if (xhr.status === 200 || xhr.status === 204) {
								resolve(xhr.responseText)
							} else {
								reject(new Error(`上传失败: ${xhr.status}`))
							}
						}
				
						xhr.onerror = () => {
							reject(new Error('上传请求失败'))
						}
						xhr.upload.onprogress = (e) => {
							let per = Math.floor((e.loaded / e.total) * 100)
				
							// 控制进度条最大显示99%，最后请求结束后才变为100%
							if (per > 99) {
								per = 99
							}
							uni.showLoading({
								title: `上传中 ${per}%`
							})
						}
						xhr.send(formData)
					})
				
					console.log('上传成功', uploadRes)
				
					this.statusMessage = '上传成功'
					uni.showToast({
						title: '上传成功',
						icon: 'success'
					})
				
					// 返回的文件URL
					const fileUrl = url;
					let audio_json = {
						src: fileUrl,
						duration
					}
					let data = {
						id: this.id,
						audio_json: JSON.stringify(audio_json)
					}
					this.$http('/api/visitsAudio', data).then(res => {
						if (res.code == 200) {
							uni.hideLoading()
							let formData = {
								visit_id: data.id,
							}
							this.$http('/api/aiAnalysis', formData, 'post').then(ress => {
								if (ress.code == 200) {
				
								}
							})
							uni.showToast({
								title: res.message,
								icon: 'none'
							})
							
						} else {
							uni.hideLoading()
							uni.showToast({
								title: res.message,
								icon: 'none'
							})
						}
					})
					console.log('文件URL:', fileUrl)
				
				} catch (error) {
					console.error('上传失败:', error)
					uni.hideLoading()
					this.statusMessage = '上传失败: ' + error.message
					uni.showToast({
						title: '上传失败',
						icon: 'none'
					})
				}
			},
		}
	}
</script>

<style lang="less" scoped>
	.container {
		box-sizing: border-box;
		background-image: url('@/static/img/log-bg.png');
		background-size: 100% 100%;
		overflow: hidden;
		position: relative;

		.content {
			.content_con {
				position: absolute;
				top: 40%;
				transform: translate(-50%, -50%);
				left: 50%;
				width: 100%;
			}

			.image_1 {
				text-align: center;
			}

			.list {
				width: 100%;
				position: absolute;
				bottom: 20%;
				color: #333;
				font-size: 40rpx;
				font-weight: 400;

				.image_3 {
					position: absolute;
					left: 2%;
					text-align: center;
					top: 50rpx;
					width: 200rpx;
					height: 200rpx;
				}

				.image_4 {
					position: absolute;
					right: 1%;
					text-align: center;
					top: 50rpx;
					width: 200rpx;
					height: 200rpx;
				}

				.image_2 {
					position: absolute;
					left: 50%;
					text-align: center;
					transform: translateX(-50%);

					.img {
						width: 300rpx;
						height: 300rpx;
						position: relative;
						display: flex;
						justify-content: center;
						align-items: center;
					}

					.text_2 {
						position: absolute;
						bottom: 0rpx;
						left: 50%;
						width: 100%;
						text-align: center;
						transform: translateX(-50%);
					}
				}
			}

			.num {
				color: #333;
				margin-top: 2vh;
				margin-bottom: 3vh;
				text-align: center;
				font-size: 40rpx;

				text {
					font-size: 62rpx;
				}
			}

			.text {
				text-align: center;
				color: #666;
				font-size: 36rpx;
			}
		}
	}
</style>